#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
设备编码工具 - 命令行版本
直接获取设备信息并显示URL
"""

import hashlib
import platform
import uuid
import psutil
import sys
import base64
import time

class AuthCode:
    """
    AuthCode加密类 - 参考PHP authcode方法实现
    """
    
    @staticmethod
    def authcode(string, operation='DECODE', key='', expiry=0, ckey_length=4):
        """
        AuthCode加密/解密方法
        """
        # 动态密钥长度, 通过动态密钥可以让相同的 string 和 key 生成不同的密文, 提高安全性
        if key == '':
            key = hashlib.md5('f4f288FTO0M5n2rX'.encode()).hexdigest()
        else:
            key = hashlib.md5(key.encode()).hexdigest()
        
        # a参与加解密, b参与数据验证, c进行密文随机变换
        keya = hashlib.md5(key[:16].encode()).hexdigest()
        keyb = hashlib.md5(key[16:].encode()).hexdigest()
        
        if ckey_length:
            if operation == 'DECODE':
                keyc = string[:ckey_length]
            else:
                keyc = hashlib.md5(str(time.time()).encode()).hexdigest()[-ckey_length:]
        else:
            keyc = ''
        
        # 参与运算的密钥组
        cryptkey = keya + hashlib.md5((keya + keyc).encode()).hexdigest()
        key_length = len(cryptkey)
        
        if operation == 'DECODE':
            # 解码时从第 ckey_length 位开始
            string = base64.b64decode(string[ckey_length:]).decode('latin-1')
        else:
            # 编码时前10位保存时间戳，10-26位保存keyb用于验证
            expiry_str = '%010d' % (expiry + int(time.time()) if expiry else 0)
            string = expiry_str + hashlib.md5((string + keyb).encode()).hexdigest()[:16] + string
        
        string_length = len(string)
        
        result = []
        box = list(range(256))
        
        # 产生密钥簿
        rndkey = []
        for i in range(256):
            rndkey.append(ord(cryptkey[i % key_length]))
        
        # 打乱密钥簿, 增加随机性
        j = 0
        for i in range(256):
            j = (j + box[i] + rndkey[i]) % 256
            box[i], box[j] = box[j], box[i]
        
        # 从密钥簿得出密钥进行异或，再转成字符
        a = j = 0
        for i in range(string_length):
            a = (a + 1) % 256
            j = (j + box[a]) % 256
            box[a], box[j] = box[j], box[a]
            
            # 使用异或运算
            result_char = ord(string[i]) ^ box[(box[a] + box[j]) % 256]
            result.append(chr(result_char))
        
        result = ''.join(result)
        
        if operation == 'DECODE':
            # 验证数据有效性和完整性
            if ((int(result[:10]) == 0 or int(result[:10]) - time.time() > 0) and 
                result[10:26] == hashlib.md5((result[26:] + keyb).encode()).hexdigest()[:16]):
                return result[26:]
            else:
                return ''
        else:
            # 把动态密钥保存在密文里, 并用 base64 编码
            encrypted = base64.b64encode(result.encode('latin-1')).decode('latin-1')
            encrypted = encrypted.replace('=', '')
            return keyc + encrypted

class DeviceTrackerCLI:
    def __init__(self):
        self.device_id = None
        self.encrypted_device_id = None
        self.target_url = "https://api.xqnmz.com/device?auth="
        
    def get_mac_address(self):
        """获取MAC地址"""
        try:
            mac = uuid.getnode()
            return ':'.join(['{:02x}'.format((mac >> elements) & 0xff) 
                           for elements in range(0, 8*6, 8)][::-1])
        except:
            return "unknown"
    
    def get_system_info(self):
        """获取系统信息"""
        return platform.system()
    
    def get_disk_serial(self):
        """获取磁盘序列号"""
        try:
            # 获取系统盘信息
            disk_info = psutil.disk_partitions()[0]
            # 使用设备路径作为标识
            return disk_info.device.replace(":", "").replace("\\", "")
        except:
            return "unknown"
    
    def generate_device_id(self):
        """生成设备唯一标识符（MD5）"""
        if self.device_id:
            return self.device_id
            
        # 拼接设备信息：磁盘序列号+系统+MAC地址
        disk_serial = self.get_disk_serial()
        system_info = self.get_system_info()
        mac_address = self.get_mac_address()
        
        device_info = f"{disk_serial}{system_info}{mac_address}"
        
        # 生成MD5哈希
        self.device_id = hashlib.md5(device_info.encode()).hexdigest()
        
        return self.device_id
    
    def encrypt_device_id(self):
        """使用authcode加密设备ID"""
        if self.encrypted_device_id:
            return self.encrypted_device_id
            
        device_id = self.generate_device_id()
        # 使用authcode加密设备ID
        self.encrypted_device_id = AuthCode.authcode(device_id, 'ENCODE', 'ai.xqnmz.dzlab.dev', 3600)
        
        return self.encrypted_device_id
    
    def get_final_url(self):
        """获取最终跳转URL"""
        encrypted_device_id = self.encrypt_device_id()
        return f"{self.target_url}{encrypted_device_id}"
    
    def display_info(self):
        """显示设备信息和URL"""
        print("=== 设备编码工具 - 命令行版本 ===")
        print()
        
        # 获取设备信息
        disk_serial = self.get_disk_serial()
        system_info = self.get_system_info()
        mac_address = self.get_mac_address()
        device_id = self.generate_device_id()
        encrypted_device_id = self.encrypt_device_id()
        final_url = self.get_final_url()
        
        print("设备信息:")
        print(f"  • 磁盘序列号: {disk_serial}")
        print(f"  • 系统信息: {system_info}")
        print(f"  • MAC地址: {mac_address}")
        print()
        
        print("生成的标识:")
        print(f"  • 设备ID (MD5): {device_id}")
        print(f"  • 加密设备ID: {encrypted_device_id}")
        print()
        
        print("最终URL:")
        print(f"  {final_url}")
        print()
        
        # 询问是否要复制URL到剪贴板
        try:
            import pyperclip
            copy_choice = input("是否复制URL到剪贴板? (y/n): ").lower().strip()
            if copy_choice in ['y', 'yes', '是']:
                pyperclip.copy(final_url)
                print("✓ URL已复制到剪贴板")
        except ImportError:
            print("提示: 安装pyperclip包可以自动复制URL到剪贴板")
        
        # 询问是否要打开浏览器
        open_choice = input("是否在浏览器中打开URL? (y/n): ").lower().strip()
        if open_choice in ['y', 'yes', '是']:
            try:
                import webbrowser
                webbrowser.open(final_url)
                print("✓ 正在打开浏览器...")
            except Exception as e:
                print(f"✗ 打开浏览器失败: {e}")
    
    def run(self):
        """运行命令行应用"""
        self.display_info()

def main():
    """主函数"""
    app = DeviceTrackerCLI()
    app.run()

if __name__ == "__main__":
    main()